#pragma once
#include <queue>
#include <pthread.h>
#include <boost/timer.hpp>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>


using namespace boost;
using namespace boost::posix_time;
using namespace std;

template <class T>
class BaseQueue
{
public:

	BaseQueue()
	{
	}
	
	virtual ~BaseQueue()
	{
	}

	int32_t size() const
	{
		return m_base_queue.size();
	}

	bool empty() const
	{
		return m_base_queue.empty();
	}

	bool push(const T &x)
	{
		{
			mutex::scoped_lock lock(m_mutex);
			m_base_queue.push(x);
		}

		m_condition_not_empty.notify_one();

		return true;
	}

	bool pop(T &x)
	{
		bool ret = false;
		
		{
			mutex::scoped_lock lock(m_mutex);

			if(!empty())
			{
				x  = m_base_queue.front();

				m_base_queue.pop();

				ret = true;
			}
			
		}
		return ret;
	}

	bool pop(T &x, const int32_t &nstime)
	{
		bool ret = false;
		
		if(nstime<0)
		{
			return false;
		}
		
		{	

			mutex::scoped_lock lock(m_mutex);

			xtime xt;
			xtime_get(&xt,TIME_UTC);
			xt.nsec +=nstime;

			while(empty())
			{
				m_condition_not_empty.timed_wait(m_mutex,xt);
			}
			
			if(!empty())
			{
				x  = m_base_queue.front();

				m_base_queue.pop();

				ret = true;
			}
		}
		return ret;
	}

	/**wait untill one x pop**/
	
	bool pop_one(T &x)
	{
		mutex::scoped_lock lock(m_mutex);

		while(empty())
		{
			m_condition_not_empty.wait(m_mutex);
		}
		
		if(!empty())
		{
			x  = m_base_queue.front();

			m_base_queue.pop();

		}
		return true;
		
	}
	
private:

	mutex	m_mutex;

	condition_variable_any m_condition_not_empty;
	
	queue<T> m_base_queue;
};

